package com.dd.shop4j.common.utils.security;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.dd.shop4j.admin.model.AdminUser;
import com.google.common.base.Objects;

/**
 * Shiro权限回调类 <br />
 * 	改类用于，用户的登录以及用户的授权
 * 	由application-shiro.xml进行配置
 * 
 * @author tangshu
 *
 */
public class ShiroDbRealm extends AuthorizingRealm {
	
	private static Logger logger = Logger.getLogger(ShiroDbRealm.class);
	
	@Resource
	private AccountService accountService;
	
	/**
	 * 认证回调函数,登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UserToken token = (UserToken) authcToken;
		if (UserType.ADMIN == token.getUserType()) {
			AdminUser adminUser = accountService.getAdminUserByUsername(token.getUsername());
			if (adminUser == null) {
				throw new DisabledAccountException("没有找到该用户");
			}
			if (token.getMD5Password().equals(adminUser.getPassword())) {
				ShiroUser shiroUser = new ShiroUser(adminUser.getUserId(),
						adminUser.getUsername(), adminUser.getRealname(), token.getHost());
				List<String> roles = accountService.getRolesCodeByUserId(adminUser.getUserId());
				for (String role : roles) {
					shiroUser.addRole(role);
				}
				List<String> resources = accountService.getResourcesCodeByUserId(adminUser.getUserId());
				for (String resource : resources) {
					shiroUser.addPermission(resource);
				}
				return new SimpleAuthenticationInfo(shiroUser, token.getPassword(), getName() + UserType.ADMIN.getCode());
			} else {
				throw new DisabledAccountException("用户名或密码错误");
			}
		} else {
			
		}
		return null;
	}
	
	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		ShiroUser user = (ShiroUser) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		logger.debug("检查用户角色和权限@" + user.getUsername());
		//加载所有角色
		for (String role : user.getRoles()) {
			info.addRole(role);
			logger.debug(user.getUsername() + "权限[" + role + "]");
		}
		//加载所有资源
		for (String permission : user.getPermissions()) {
			info.addStringPermission(permission);
			logger.debug(user.getUsername() + "资源[" + permission + "]");
		}
		return info;
	}
	
	/**
	 * 自定登录用户类，用户将登录的用户信息保存到系统中
	 * @author tangshu
	 *
	 */
	public class ShiroUser implements Serializable {

		private static final long serialVersionUID = -3015384574718728146L;
		
		private Integer userId;		//数据库主键
		private String username;	//用户名
		private String realname;	//真实姓名
		private String host;		//访问ip
		private List<String> roles;	//所有角色
		private List<String> permissions; //所有资源

		public ShiroUser() {
		}

		public ShiroUser(Integer userId, String username, String realname, String host) {
			super();
			this.userId = userId;
			this.username = username;
			this.realname = realname;
			this.host = host;
		}

		public Integer getUserId() {
			return userId;
		}
		
		public void setUserId(Integer userId) {
			this.userId = userId;
		}

		public String getUsername() {
			return username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

		public String getRealname() {
			return realname;
		}

		public void setRealname(String realname) {
			this.realname = realname;
		}

		public String getHost() {
			return host;
		}
		
		public void setHost(String host) {
			this.host = host;
		}
		
		public List<String> getRoles() {
			return roles;
		}

		public void setRoles(List<String> roles) {
			this.roles = roles;
		}

		public List<String> getPermissions() {
			return permissions;
		}

		public void setPermissions(List<String> permissions) {
			this.permissions = permissions;
		}

		/**
		 * 为用户添加一个角色
		 * @param role
		 */
		public void addRole(String role) {
			if (roles == null) {
				setRoles(new ArrayList<String>());
			}
			if (!roles.contains(role)) {
				roles.add(role);
			}
		}
		
		/**
		 * 为用户添加一个资源
		 * @param permission
		 */
		public void addPermission(String permission) {
			if (permissions == null) {
				setPermissions(new ArrayList<String>());
			}
			if (!permissions.contains(permission)) {
				permissions.add(permission);
			}
		}
		
		/**
		 * 本函数输出将作为默认的<shiro:principal/>输出.
		 */
		@Override
		public String toString() {
			return realname;
		}
		
		/**
		 * 重载hashCode,只计算username;
		 */
		@Override
		public int hashCode() {
			return Objects.hashCode(username);
		}
		
		/**
		 * 重载equals,只计算username;
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			ShiroUser other = (ShiroUser) obj;
			if (username == null) {
				if (other.username != null)
					return false;
			} else if (!username.equals(other.username))
				return false;
			return true;
		}
	}
	
}